(function ($, undefined) {

    "use strict";

    $.fn.megaMenu = function (options) {

		var settings = $.extend({
			expandOnHover: function() { return false; },
			expandClickTarget: null,
		}, options);
	
		if (typeof settings.expandOnHover !== "function") {
			var v = settings.expandOnHover;
			settings.expandOnHover = function() { return v; }
		}
		
        return this.each(function () {

            var menu = $(this);

            function closeSubMenu() {
                menu.removeClass("sub-menu-expanded");
                menu.children(".expanded").removeClass("expanded");
                $("html").unbind("click.mega-menu");
            }

            function expandSubMenu(menuItem) {

                closeSubMenu();

                menu.addClass("sub-menu-expanded");
                menuItem.addClass("expanded");

                $("html").bind("click.mega-menu", function (e) {
                    if (menu[0] !== e.target && $.contains(menu[0], e.target) === false) {
                        closeSubMenu();
                    }
                });
            }

            function expandNextSubMenu() {
                var nextMenuItem = menu.children(".expanded").next();
                if (nextMenuItem.length === 0) {
                    nextMenuItem = menu.children().first();
                }
                expandSubMenu(nextMenuItem);
            }

            function expandPreviousSubMenu() {
                var previousMenuItem = menu.children(".expanded").prev();
                if (previousMenuItem.length === 0) {
                    previousMenuItem = menu.children().last();
                }
                expandSubMenu(previousMenuItem);
            }

            menu.keypress(function (e) {
                if (e.keyCode === 39) {
                    expandNextSubMenu();
                } else if (e.keyCode === 37) {
                    expandPreviousSubMenu();
                } else if (e.keyCode === 27) {
                    closeSubMenu();
                }
            });

			var expandClickTarget = settings.expandClickTarget ? menu.find(settings.expandClickTarget) : menu.children();
			
            expandClickTarget.click(function (e) {
				if (settings.expandOnHover())
					return;
				
				//
				// If click target is a child of a menu item, find the menu item
				//
				var menuItem = (this.tagName === "li") ? $(this) : $(this).closest("li");

				//
				// If click target is inside the sub menu, ignore the click
				//
				var subMenu = menuItem.find('.sub-menu');
				if (subMenu.length > 0 && $.contains(subMenu[0], e.target))
					return;
					
				if (menuItem.hasClass('expanded')) {
					closeSubMenu();
				} else {				
					expandSubMenu(menuItem);
				}
				
				e.preventDefault();
				e.stopImmediatePropagation();
            });

			menu.children().hover(
				function (e) { 
					if (settings.expandOnHover() == false) 
						return;
					expandSubMenu($(this)); 
				},
				function(e) { 
					if (settings.expandOnHover() == false) 
						return;
					closeSubMenu(); 
				});
			
			menu.click(function(e) {			
				if (e.target !== menu[0]) 
					return;
				
				$(this).toggleClass('expanded');
				
				e.preventDefault();
				e.stopImmediatePropagation();
			});
        });
    };
})(jQuery);